package KademliaDht

import (
	"container/vector"
	"os"
//	"fmt"
)

type KadBucketList struct {
	K		int
	Buckets	*vector.Vector
	I		[]int
}

func New_KadBucketList( k int ) *KadBucketList {
	return &KadBucketList{ k, new( vector.Vector ), make( []int, 0, 0 ) }
}

func ( kl * KadBucketList ) Len() int {
	return kl.Buckets.Len()
}

func ( kl * KadBucketList ) At( index int ) *KadBucket {
	return kl.Buckets.At( index ).( *KadBucket )
}

func ( kl * KadBucketList ) Spotted( c * KadContact, dist uint64 ) {
	// Can't spot himself
	if dist != 0 {
		//fDist := float64( dist )
		kl.createBuckets( dist )
		/*if ( kl.Buckets.Len() == 0 ) {
			kl.createBuckets( dist )
		} else {
			bk := kl.Buckets.Last().( *KadBucket )
			if( bk.MaxDistance < dist ) {
				kl.createBuckets( dist )
			}
		}*/
		found := false
		for i := 0; i < kl.Buckets.Len() && !found; i++ {
			bk := kl.Buckets.At( i ).( *KadBucket )
			// Max 63 Buckets
			if(  dist >= bk.MinDistance && dist <= bk.MaxDistance ) || i == 63 {
				bk.Spotted( c )
				found = true
			}
		}
		if !found {
		}
	}
}

func ( kl * KadBucketList ) createBuckets( dist uint64 ) {
	//fDist := float64( dist )
	if kl.Buckets.Len() == 63 {
		return
	}
	if kl.Buckets.Len() == 0 {
		kl.Buckets.Push( New_KadBucket(  kl.Buckets.Len(), kl.K ) )
	}
	for dist > kl.Buckets.Last().( *KadBucket ).MaxDistance && kl.Len() < 63 {
		kl.Buckets.Push( New_KadBucket(  kl.Buckets.Len(), kl.K ) )
	}
}

// TODO: Make possible to return contacts from multiple buckets
func ( kl * KadBucketList ) FindBucket( dist uint64 ) ( kcontacts []*KadContact, error os.Error ) {
	//fDist := float64( dist )
	res := make( []*KadContact, 0, 0 )
	if kl.Buckets.Len() == 0 {
		return res, nil
	}
	var bkI int
	for i := 0; i < kl.Buckets.Len(); i++ {
		bk := kl.Buckets.At( i ).( *KadBucket )
		if (  dist >= bk.MinDistance ) && ( dist <= bk.MaxDistance ) {
			res = append( res, bk.GetSlice()... )
			bkI = i
		}
	}
	// No bucket for that distance
	if len( res ) == 0 {
		res = append( res, kl.Buckets.Last().( *KadBucket ).GetSlice()... )
		bkI = kl.Len() - 1
	}
	
	more := true
	for j := 1; len( res ) < kl.K && more; j++ {
		if bkI - j >= 0 {
			res = append( res, kl.Buckets.At( bkI - j ).( *KadBucket ).GetSlice()... )
			more = true
		} else {
			more = false
		}
		
		if bkI + j < kl.Buckets.Len() {
			res = append( res, kl.Buckets.At( bkI + j ).( *KadBucket ).GetSlice()... )
			more = true
		} else {
			more = more || false
		}
	}
	
	return res, nil
}

